package com.chasing.baseframe.widgets.popup;

import android.animation.Animator;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.OvershootInterpolator;
import android.widget.PopupWindow;

import androidx.annotation.AnimRes;
import androidx.core.content.ContextCompat;

import com.chasing.baseframe.R;

import net.chasing.androidbaseconfig.util.ActivityUtils;
import net.chasing.androidbaseconfig.util.AnimatorUtil;
import net.chasing.androidbaseconfig.util.GenericTools;
import net.chasing.androidbaseconfig.util.OneClickUtil;
import net.chasing.androidbaseconfig.util.RomUtils;

/**
 * 注：
 * PopupWindow内使用EditText会不能进行长按
 * <p>
 * 需要对mBackgroundView及mContentView进行赋值初始化才能进行相应动画效果
 * mBackgroundView用于动画执行设置，不需要动画的话可以不进行设置
 * mContentView用于启动弹出动画，不需要动画的话可以不进行设置
 * 默认是底部弹出动画，通过重写doSomethingBeforeInit()，修改mEnterAnim、mExitAnim
 * <p>
 * 如果可视布局是在底部的(默认isClippingEnabled = false是会覆盖底部虚拟导航栏)
 * 则需要根据底部是否存在虚拟导航栏进行切换marginBottom/paddingBottom
 * 调用setMarginBottomByCheckBottomNavBar/setPaddingBottomByCheckBottomNavBar传入需要设置的view即可
 * <p>
 * 注：默认isClippingEnabled = false是会覆盖底部虚拟导航栏
 * 会导致软键盘无法顶起输入控件，即会覆盖在输入控件上
 * <p>
 * setMarginBottomByCheckBottomNavBar和setPaddingBottomByCheckBottomNavBar
 * 只有在onWindowFocusChanged之后才有效果，Aty在完全加载视图前获取不到底部导航栏的
 * <p>
 * 注：popupWindow不能在Activity刚创建（包括onCreate、onStart、onResume）的时候进行弹出，否则会报
 * token null is not valid; is your activity running?
 * 可以使用已下方式：
 * 重写：因为window已经获取到焦点了，对用户是可见的了，说明Activity已经创建完毕了
 * public void onWindowFocusChanged(boolean hasFocus) {
 * super.onWindowFocusChanged(hasFocus);
 * if (hasFocus && !hadCheckedForm){
 * hadCheckedForm = true;
 * if (!UserManager.getInstance().getLoginUser().isSignUpCompetition())
 * showFormPopup();
 * }
 * }
 */
public abstract class BasePopupWindow extends PopupWindow {
    protected View mBackgroundView;
    protected View mContainView;

    protected OneClickUtil mOneClickUtil;
    protected Context mContext;
    private Animation mAnimEnter;
    private Animation mAnimExit;
    protected @AnimRes int mEnterAnim = net.chasing.androidbaseconfig.R.anim.pop_bottom_enter;
    protected @AnimRes int mExitAnim = net.chasing.androidbaseconfig.R.anim.pop_bottom_exit;
    protected boolean isBottomEnter = true;

    // 是否不覆盖状态栏，true则内容不会覆盖状态栏，false则会；false会导致软键盘无法顶起输入控件，即会覆盖在输入控件上
    protected boolean isClippingEnabled = false;
    // 是否需要切换虚拟导航栏图标颜色 -- 手动判断，如果弹窗视图底部没有使用白色背景覆盖到虚拟导航栏，则为false无需切换黑色
    protected boolean isShouldChangeNavigation = true;
    // 是否需要切换虚拟导航栏图标颜色 -- 程序判断，有虚拟导航栏且isShouldChangeNavigation为true时才为true
    private boolean needChangeNavigation;
    // 虚拟导航栏图标颜色是否是黑色
    private boolean isDarkNavigation;

    public BasePopupWindow(Context context) {
        super(context);
        mContext = context;
        mOneClickUtil = new OneClickUtil();
        doSomethingBeforeInit();
        setFocusable(true);
        setOutsideTouchable(false);
        //背景必须进行设置，否则4.x  5.x的安卓将无法点击空白及返回键关闭popupWindow
        setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(context, net.chasing.androidbaseconfig.R.color.transparent)));
        setClippingEnabled(isClippingEnabled);

        setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        setHeight(ViewGroup.LayoutParams.MATCH_PARENT);

        initAnim(context);
    }

    protected void doSomethingBeforeInit() {
    }

    public void initAnim(Context context) {
        mAnimEnter = AnimationUtils.loadAnimation(context, mEnterAnim);
        mAnimExit = AnimationUtils.loadAnimation(context, mExitAnim);
        mAnimEnter.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                if (mBackgroundView != null)
                    mBackgroundView.setVisibility(View.VISIBLE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        mAnimExit.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                if (mBackgroundView != null)
                    mBackgroundView.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                onExitAnimationEnd();
                dismiss();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

    // 设置使动画支持回弹模式
    public void setAnimOvershoot() {
        if (mAnimEnter != null && mContainView != null) {
            mAnimEnter.setInterpolator(new OvershootInterpolator(1.05f));
            mContainView.post(() -> {
                double addPaddingBottom = mContainView.getHeight() * 0.1;
                mContainView.setPadding(mContainView.getPaddingStart(), mContainView.getPaddingTop(),
                        mContainView.getPaddingEnd(), (int) (mContainView.getPaddingBottom() + addPaddingBottom));
                mContainView.setTranslationY((float) (mContainView.getTranslationY() + addPaddingBottom));
            });
        }
    }

    private boolean hadAddBottomSpace;

    public void setMarginBottomByCheckBottomNavBar(View view) {
        if (hadAddBottomSpace) return;
        if (!isClippingEnabled) { // 只有布局遮盖着导航栏才需要进行移动
            int navigationHeight = GenericTools.getNavigationBarHeight((Activity) mContext);
            if (navigationHeight > 0) {
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
                navigationHeight += layoutParams.bottomMargin;
                layoutParams.bottomMargin = navigationHeight;
                view.setLayoutParams(layoutParams);
                if (isShouldChangeNavigation)
                    needChangeNavigation = true;
                hadAddBottomSpace = true;
            }
        }
    }

    public void setPaddingBottomByCheckBottomNavBar(View view) {
        if (hadAddBottomSpace) return;
        if (!isClippingEnabled) { // 只有布局遮盖着导航栏才需要进行移动
            int navigationHeight = GenericTools.getNavigationBarHeight((Activity) mContext);
            if (navigationHeight > 0) {
                navigationHeight += view.getPaddingBottom();
                view.setPadding(view.getPaddingStart(), view.getPaddingTop(), view.getPaddingEnd(), navigationHeight);
                if (isShouldChangeNavigation)
                    needChangeNavigation = true;
                hadAddBottomSpace = true;
            }
        }
    }

    public void removePaddingBottomByCheckBottomNavBar(View view) {
        if (!hadAddBottomSpace) return;
        if (!isClippingEnabled) { // 只有布局遮盖着导航栏才需要进行移动
            int navigationHeight = GenericTools.getNavigationBarHeight((Activity) mContext);
            if (navigationHeight > 0) {
                int bottom = view.getPaddingBottom();
                bottom -= navigationHeight;
                view.setPadding(view.getPaddingStart(), view.getPaddingTop(), view.getPaddingEnd(), bottom);
                if (isShouldChangeNavigation)
                    needChangeNavigation = true;
                hadAddBottomSpace = false;
            }
        }
    }

    private void changeNavigationBar(boolean isDark) {
        if (isDark != isDarkNavigation) {
            try {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    Window window = ((Activity) mContext).getWindow();
                    if (window != null) {
                        int i;
                        if (isDark)
                            i = window.getDecorView().getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
                        else
                            i = window.getDecorView().getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
                        window.getDecorView().setSystemUiVisibility(i);
                        isDarkNavigation = isDark;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    protected void onExitAnimationEnd() {

    }

    public void show(View view) {
        showAtLocation(view, Gravity.BOTTOM, 0, 0);
    }

    @Override
    public void dismiss() {
        if (mContainView != null && mAnimExit != null &&
                mBackgroundView != null && mBackgroundView.getVisibility() == View.VISIBLE)
            mContainView.startAnimation(mAnimExit);
        else {
            super.dismiss();
            if (needChangeNavigation && isDarkNavigation) {
                changeNavigationBar(false);
            }
            if (mBackgroundView != null)
                mBackgroundView.setVisibility(View.GONE);
        }
    }

    /**
     * 注：showAsDropDown布局不会覆盖到虚拟导航栏上，
     * 如果布局高度过高，则会导致布局向上移覆盖到anchor
     * 需要布局覆盖到虚拟导航栏上则使用showAtLocation
     */
    @Override
    public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
        if (mContext instanceof Activity) {
            if (((Activity) mContext).isFinishing()) return;
        } else if (anchor == null || isShowing())
            return;
        super.showAsDropDown(anchor, xoff, yoff, gravity);
        if (needChangeNavigation)
            changeNavigationBar(true);

        if (mContainView != null && mAnimEnter != null)
            startEnterAnim();
        else if (mBackgroundView != null)
            mBackgroundView.setVisibility(View.VISIBLE);
    }

    @Override
    public void showAtLocation(View parent, int gravity, int x, int y) {
        if (mContext instanceof Activity) {
            if (((Activity) mContext).isFinishing()) return;
        } else if (parent == null || isShowing())
            return;
        super.showAtLocation(parent, gravity, x, y);
        if (needChangeNavigation)
            changeNavigationBar(true);

        if (mContainView != null && mAnimEnter != null)
            startEnterAnim();
        else if (mBackgroundView != null)
            mBackgroundView.setVisibility(View.VISIBLE);
    }

    public void showAsDropDownOrAtLocation(View root, View line) {
        // 小米的小窗口模式，不能使用showAsDropDown
        if (RomUtils.isXiaomi() && ActivityUtils.isInMultiWindowMode(mContext)) {
            // 因为导航栏高度读取会发生变化，系统问题，所以只能尝试使用写死大小的方式
            int navigationBarHeight = mContext.getResources().getDimensionPixelSize(net.chasing.androidbaseconfig.R.dimen.xiaomi_navigation_bar_height);
            showAtLocation(root, Gravity.BOTTOM, 0, navigationBarHeight);
        } else
            showAsDropDown(line);
    }

    private void startEnterAnim() {
        int containHeight = mContainView.getHeight();
        if (containHeight > 0) {
            AnimatorUtil.translationY(mContainView, 200, new AnimatorUtil.OnAnimation() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    mBackgroundView.setVisibility(View.VISIBLE);
                }
            }, isBottomEnter ? containHeight : -containHeight, 0);
        } else
            mContainView.startAnimation(mAnimEnter);
    }
}
